-- 游戏服的总入口
-- 如果玩家在某张桌子上，则请求转发给桌子 service来执行

local filename = "router.lua"

local skynet = require "skynet"
local cluster = require "skynet.cluster"
require "skynet.manager"

local filelog = require "filelog"
local routerbase = require "routerbase"

require "brnnenum"

local Router = routerbase:new({
	idle_table_mng = nil,	-- 空闲桌子生成器
	-- 这里容易混淆，有一个是桌子table的自然编号 1，2，3，4，5，变量名为index
	-- 一个是桌子的随机码（编码），变量名为code
	index_to_table = {},	-- 通过桌子的内部序列号（index）来找到桌子，可以用在节点重启后重构桌子(tablemap 是个整体)
							-- {index=table_service}
	code_to_index = {},	    -- 通过桌子的编码(code) 来找到 index {code=index}
	table_index = 1,	    -- 序列号，自增调用，既方便管理，也是桌子的主索引
	role_map = {}, 			-- 主键就是rid
    diff_level_players = {},--不同场次玩家数
    game_table_list = {     -- 游戏桌列表
        idle_table = { },   -- 空位桌子列表,内含3个list，对应3种场次,每个list元素为： table_index
    },    
})

function Router:init()
	self:add_func("nodemsg/noderequest")
    self:add_func("nodemsg/nodecmd")
end

-----------------

--
-- 保存角色到桌子的映射关系
-- 通知gate玩家进桌
--
function Router:forward(rid, tableservice, table_index, coin)
	if self.role_map[rid] == nil then
        if table_index and self.index_to_table[table_index] then
            local level = self.index_to_table[table_index].level_type
            self.diff_level_players[level] = (self.diff_level_players[level] or 0) + 1
        end

		self.role_map[rid] = { table_service = tableservice,table_index = table_index }
        --local status, result = skynet.call(".agentmgr", "lua", "cmd", "set_tableaddress_by_rid", rid, tableservice)
		status = skynet.pcall(cluster.send,"gatenode", ".router", "role_enter_table", rid, skynet.getenv("nodename"), table_index,coin)
        if not status then
            filelog.sys_error("call gatenode error!")
        else
            filelog.print(rid ,"enter table")
        end
	end
end

--
-- 取消角色到桌子的映射关系
-- 通知gate玩家离桌
--
function Router:unforward(rid, table_index, coin)
	if self.role_map[rid] then
        if table_index ~= self.role_map[rid].table_index then
            table_index = self.role_map[rid].table_index or table_index
            filelog.sys_error("-----------error table_index---------", rid, table_index)
        end
		self.role_map[rid] = nil
        if table_index and self.index_to_table[table_index] then
            local level = self.index_to_table[table_index].level_type
            self.diff_level_players[level] = (self.diff_level_players[level] or 0) - 1
        end
    end
    --local status, result = skynet.call(".agentmgr", "lua", "cmd", "clear_tableaddress_by_rid", rid)
	local status = skynet.pcall(cluster.send,"gatenode", ".router", "role_leave_table", rid, skynet.getenv("nodename"), table_index, coin)
    if not status then
        filelog.sys_error("call gatenode error!")
    else
        filelog.print(rid ,"leave table")
    end
end

--
-- 获得一个uuid
--
function Router:get_tradeid()
    return skynet.call(".nodeuuid", "lua", "getuuid")
end

--
--获取玩家数据
--
function Router:get_role_data(rid)
    return self.role_map[rid]
end

-------------------
-- 测试接口

--
--查看游戏状态
--
local function watch()
    while true do
        skynet.sleep(53 *100)
        skynet.send(".router", "lua","cmd", "getgamestate")
    end
end

--
--检测游戏状态
--
local function check()
    while true do
        skynet.sleep(37 *100)
        skynet.send(".router", "lua","cmd", "checkgamestate")
    end
end

-------------------
--服务入口

skynet.start(function()
    skynet.dispatch("lua", 
        function (session, source, command, rid, arg1, ...)
	        local status = true
            local result = nil
            if Router[command] then
                local func = Router[command]
                result = func(Router,rid,arg1,...)
                return skynet.retpack(result)
            end
	        if rid and Router.role_map[rid] and Router.role_map[rid].table_service then
			    status, result = skynet.pcall(skynet.call, Router.role_map[rid].table_service, "lua", "request", command, rid, arg1, ...)
		        if not status then
			        filelog.sys_error("call table service failed!", rid)
                    Router:unforward(rid, Router.role_map[rid].table_index, 0)
			        result = {retcode = EErrCode.ERR_SYSTEM_ERROR, retstr = "call_table_service_failed"}
		        end
	        else
		        local f = Router.CMD[command]
		        if f == nil then
			        filelog.sys_error("line44" .. filename.." CMD[command] is nil : ", rid, command)
			        result = {retcode = EErrCode.ERR_NOT_INTABLE, retstr = "role_not_in game_table"}
		        else
			        if type(f) == "function" then
                        if  rid == nil then
                            status, result = skynet.pcall(f, arg1, ... )
                        elseif rid == 0 then
                            result = {retcode = EErrCode.ERR_INVALID_REQUEST, retstr = "无效的用户id"}
                        else
					        status, result = skynet.pcall(f, rid, arg1, ... )
                        end
				        if not status then
					        filelog.sys_error(filename.." CMD[command] skynet.pcall failed : ", command, rid, result, arg1, ...)
				        end
			        else
				        filelog.sys_error("role not in game table!",command)
				        result = {retcode = EErrCode.ERR_NOT_INTABLE, retstr = "role_not_in game_table"}
			        end
		        end
	        end
	        skynet.retpack(result)
    end)
    Router:init()

    --测试
    skynet.fork(watch)
    skynet.fork(check)
end)
